package com.xaicode.algorithm.redis;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * ConcurrentHashMap + ConcurrentLinkedQueue
 *
 * @author Locker cjxia@isoftstone.com
 * @version 1.0
 */
public class LRUCache2<K, V> {

    private final int maxSize;
    private ConcurrentHashMap<K, V> map;
    private ConcurrentLinkedQueue<K> queue;

    public LRUCache2(final int maxSize) {
        this.maxSize = maxSize;
        map = new ConcurrentHashMap<>(maxSize);
        queue = new ConcurrentLinkedQueue<>();
    }

    public void put(final K key, final V value) {
        if (map.containsKey(key)) {
            queue.remove(key);
        }
        while (queue.size() >= maxSize) {
            K oldestKey = queue.poll();
            if (null != oldestKey) {
                map.remove(oldestKey);
            }
        }
        queue.add(key);
        map.put(key, value);
    }

    public V get(final K key) {
        if (map.containsKey(key)) {
            queue.remove(key);
            queue.add(key);
        }
        return map.get(key);
    }

    public static void main(String[] args) {

//        Integer[] arr = new Integer[5];
//        Arrays.parallelSetAll(arr, Integer::new);
//        List<Integer> list = Arrays.asList(arr);
//        final Iterator<Integer> iterator = list.iterator();
//        while (iterator.hasNext()) {
//            System.out.println(iterator.next());
//        }
//        return;

//        ConcurrentLinkedQueue<String> q = new ConcurrentLinkedQueue<>();
//        IntStream.range(0, 5).parallel().forEach(i -> q.add(i + ""));
//        for (String s : q) {
//            System.out.println(s);
//        }


        LRUCache2<String, String> c = new LRUCache2<>(3);
        c.put("1", "one");
        c.put("2", "two");
        c.put("3", "three");
        c.put("4", "four");
        assert c.get("2") != null;
        c.put("5", "five");
        c.put("4", "second four");

        Iterator<String> iterator = c.queue.iterator();
        while (iterator.hasNext()) {
            String newKey = iterator.next();
            System.out.printf("key: %s, val: %s\n", newKey, c.map.get(newKey));
        }

        System.out.println("------------");

        for (Iterator<String> iterator2 = c.queue.iterator(); iterator2.hasNext(); ) {
            String newKey = iterator2.next();
            System.out.printf("key: %s, val: %s\n", newKey, c.map.get(newKey));
        }

    }

}
